package cn.demoncat.util.web.entity;

import cn.demoncat.util.lang.StringUtil;
import cn.demoncat.util.web.ServletUtil;
import cn.demoncat.util.web.UrlUtil;
import cn.demoncat.util.web.WebUtil;
import cn.demoncat.util.web.constant.AgentConstant;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

/**
 * 访问信息
 * 
 * @author 延晓磊
 *
 * @since 2018年12月25日
 */
@Data
public class Access {

	// 访问ID
	private String id;
	// 服务ID
	private String appId;
	// 用户ID
	private Long userId;
	// 请求url
	private String uri;
	// 请求Method
	private String method;
	// 是否为内部REST请求
	private Boolean isRest;
	// 来源IP
	private String ip;
	// 来源端口
	private Integer port;
	// 来源页面
	private String referer;
	// 来源Token
	private String token;
	// 客户端原生Token
	private String ctoken;
	// Token扩展参数
	private String tokenExtend;
	// 请求参数（Query参数 + Form参数 + Json-Body）
	private Map<String, String> params;
	// 用户代理信息（浏览器和设备）
	private Agent agent;

	// Json-Body 参数名
	private static String JSON_BODY_PARAM = "json_body";

	/**
	 * 是否为PC端请求
	 *
	 * @return
	 *
	 * @author 延晓磊
	 * @since 2022年09月05日
	 */
	public boolean isPc(){
		Agent agent = this.getAgent();
		if (agent != null) {
			return AgentConstant.SystemType.COMPUTER.equals(agent.getSystemType());
		}
		return false;
	}

	/**
	 * 设置Request
	 *
	 * @param request
	 *
	 * @author 延晓磊
	 *
	 * @since 2019年5月30日
	 */
	@JSONField(serialize=false,deserialize=false)
	public void setRequest(HttpServletRequest request) {
		// 请求
		this.uri = WebUtil.getRequestPath(request);
		this.method = request.getMethod();
		this.ip = WebUtil.getIpAddr(request);
		this.port = request.getRemotePort();
		this.isRest = UrlUtil.isRestUrl(this.uri);
		// 参数
		this.params = ServletUtil.getParams(request);
		StringUtil.consumer(ServletUtil.getJsonBody(request), json -> this.params.put(JSON_BODY_PARAM, json));
	}

	/**
	 * 获取Request
	 * 
	 * 1、只能在本线程中获取（异步线程中不要使用）
	 * 2、为了回避清除、变更、转发、大对象等麻烦，统一使用RequestContextHolder中的局部变量，而不单独保存
	 * 
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年5月30日
	 */
	@JSONField(serialize=false,deserialize=false)
	public HttpServletRequest getRequest() {
		return ServletUtil.getRequest();
	}

	/**
	 * 获取Response
	 * 
	 * 1、只能在本线程中获取（异步线程中不要使用）
	 * 2、为了回避清除、变更、转发、大对象等麻烦，统一使用RequestContextHolder中的局部变量，而不单独保存
	 * 
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年5月30日
	 */
	@JSONField(serialize=false,deserialize=false)
	public HttpServletResponse getResponse() {
		return ServletUtil.getResponse();
	}

	/**
	 * 获取参数
	 * 
	 * @param name
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年5月30日
	 */
	@JSONField(serialize=false,deserialize=false)
	public String getParam(String name) {
		return this.params.get(name);
	}

	/**
	 * 获取JsonBody参数
	 *
	 * @return
	 *
	 * @author 延晓磊
	 *
	 * @since 2019年5月30日
	 */
	@JSONField(serialize=false,deserialize=false)
	public String getJsonBody() {
		return this.params.get(JSON_BODY_PARAM);
	}

	/**
	 * 读取Access填充Agent
	 * 
	 * @param access
	 * @param agent
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年9月11日
	 */
	public static void fillAgent(Access access, Agent agent) {
		if (access.getAgent() != null) {
			agent.setBrowser(access.getAgent().getBrowser());
			agent.setBrowserName(access.getAgent().getBrowserName());
			agent.setBrowserType(access.getAgent().getBrowserType());
			agent.setBrowserVersion(access.getAgent().getBrowserVersion());
			agent.setSystem(access.getAgent().getSystem());
			agent.setSystemName(access.getAgent().getSystemName());
			agent.setSystemType(access.getAgent().getSystemType());
		}
	}

}
